﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;
using RedRiver.Framework.XtraCommon.FormHelper;

namespace RedRiver.Framework.XtraCommon.Templates{
    public partial class DataViewForm : XtraCommonForm, IDataViewForm{
        /// <summary>
        /// 编辑器是否已经初始化
        /// </summary>
        protected bool IsEditorsInited;

        /// <summary>
        /// 位置记录
        /// </summary>
        private int _lastPosition;

        /// <summary>
        /// 数据操作规则
        /// </summary>
        private DataManipulateRule _manipulateRule;

        public DataViewForm(){
            InitializeComponent();
            _manipulateRule = DataManipulateRule.None;
            _lastPosition = -1;
        }

        /// <summary>
        /// 默认窗体的数据源
        /// </summary>
        public virtual BindingSource DefaultBindingSource{
            get { return defaultBindingSource; }
        }

        /// <summary>
        /// 数据操作规则
        /// </summary>
        public DataManipulateRule ManipulateRule{
            get { return _manipulateRule; }
            set{
                _manipulateRule = value;
                if ((!DesignMode)&&(IsEditorsInited)){
                    OnManipulateRuleChange(value);
                }
            }
        }

        #region IDataViewForm Members

        /// <summary>
        /// 默认绑定管理器
        /// </summary>
        public virtual CurrencyManager DefaultBinding{
            get { return DefaultBindingSource.CurrencyManager; }
        }

        /// <summary>
        /// 只读控件集合
        /// </summary>
        protected List<BaseEdit> ReadOnlyBaseEdits{
            get{
                if(_readOnlyBaseEdits == null){
                    _readOnlyBaseEdits = new List<BaseEdit>();
                }
                return _readOnlyBaseEdits;
            }
        }

        /// <summary>
        /// 只读表格列集合
        /// </summary>
        protected List<GridColumn> ReadOnlyGridColumns{
            get{
                if(_readOnlyGridColumns == null){
                    _readOnlyGridColumns = new List<GridColumn>();
                }
                return _readOnlyGridColumns;
            }
        }

        /// <summary>
        /// 自定义的数据加载方法
        /// </summary>
        public virtual void LoadData(){
            XtraMessageForm.ShowMessage("正在加载数据...");
            try{
                BeginLoadData();
                OnLoadData();
                EndLoadData();
                RefreshState();
                XtraMessageForm.Hiden();
            } catch (Exception ex){
                XtraMessageForm.ShowException("加载数据过程出现异常", ex);
            }
        }

        /// <summary>
        /// 加载数据方法,能够辨识的数据类型为 DataSet,DataTable,DataRow,DataView,DataRowView
        /// <seealso cref="DataSet.Merge(System.Data.DataSet)"></seealso>
        /// </summary>
        /// <param name="data"></param>
        public virtual void LoadData(object data){
            if (defaultBindingSource.DataSource == null){
                defaultBindingSource.DataSource = data;
            }
            if (defaultBindingSource.DataSource is DataSet){
                var dataSource = (DataSet) defaultBindingSource.DataSource;
                dataSource.MergeData(data);
            } else if (defaultBindingSource.DataSource is DataTable){
                var dataSource = (DataTable) defaultBindingSource.DataSource;
                dataSource.MergeData(data);
            } else{
                defaultBindingSource.DataSource = data;
            }
        }

        /// <summary>
        /// 自定义的数据保存方法
        /// 继承类具体实现数据更新的方法需要覆盖<see cref="OnUpdateData"/>方法
        /// </summary>
        public void UpdateData(){
            if (!Assert(DataManipulateRule.AllEdit)){
                throw new NotSupportedException("当前权限不支持编辑操作");
            }
            try{
                XtraMessageForm.ShowMessage("正在提交数据...");
                if (DataValidate()){
                    OnUpdateData();
                    RefreshState();
                    _isDataChanged = true;
                }
                XtraMessageForm.Hiden();
            } catch (Exception ex){
                XtraMessageForm.ShowException("提交数据过程发生异常," + ex.Message, ex);
            }
        }

        #endregion

        /// <summary>
        /// 当刷新数据时执行
        /// </summary>
        public virtual void OnRefreshData(){
            LoadData();
        }

        /// <summary>
        /// 在加载窗体之前,初始化编辑器
        /// </summary>
        protected virtual void InitEditors(){
            IsEditorsInited = true;
            AddReadOnlyItems();
            OnManipulateRuleChange(ManipulateRule);
        }

        /// <summary>
        /// 只读控件集合
        /// </summary>
        private List<BaseEdit> _readOnlyBaseEdits ;
        /// <summary>
        /// 只读表格列集合
        /// </summary>
        private List<GridColumn> _readOnlyGridColumns;

        private bool _isDataChanged;

        /// <summary>
        /// 数据是否改变并保存
        /// <remarks>
        /// 如果返回结果为 True 则需要重新加载
        /// 当数据改变并且提交成功后,返回值为True,否则为False
        /// </remarks>
        /// </summary>
        /// <returns></returns>
        public bool IsDataChanged {
            get {
                return _isDataChanged;
            }
        }

        /// <summary>
        /// 默认的 增加只读控件方法
        /// </summary>
        protected virtual void AddReadOnlyItems(){}

        protected void AddReadOnlyItems(IEnumerable<BaseEdit> controls) {
            if(controls==null){
                return;
            }
            ReadOnlyBaseEdits.AddRange(controls.Except(ReadOnlyBaseEdits));
        }

        protected void AddReadOnlyItems(IEnumerable<GridControl> grids){
            if(grids == null){
                return;
            }
            foreach (var grid in grids){
                AddReadOnlyItems(grid.Views.OfType<ColumnView>());
            }
        }

        protected void AddReadOnlyItems(IEnumerable<ColumnView> views) {
            if (views == null) {
                return;
            }
            foreach (var view in views){
                ReadOnlyGridColumns.AddRange(view.Columns.OfType<GridColumn>().Where(c => c.OptionsColumn.ReadOnly).Except(ReadOnlyGridColumns));
            }
        }

        /// <summary>
        /// 手动添加 只读控件集合
        /// </summary>
        /// <param name="columns"></param>
        protected void AddReadOnlyItems(params GridColumn[] columns) {
            if(columns == null){
                return;
            }
            ReadOnlyGridColumns.AddRange(columns.Except(ReadOnlyGridColumns));
        }
        /// <summary>
        /// 手动添加 只读控件集合
        /// </summary>
        /// <param name="controls"></param>
        protected void AddReadOnlyItems(params BaseEdit[] controls) {
            if((controls == null)||(controls.Length ==0)){
                return;
            }
            ReadOnlyBaseEdits.AddRange(controls.Except(ReadOnlyBaseEdits));
        }

        /// <summary>
        /// 设置指定的控件只读属性
        /// </summary>
        protected void SetItemsReadOnly(){
            if(_readOnlyBaseEdits!=null){
                foreach(var edit in _readOnlyBaseEdits){
                    edit.Properties.ReadOnly = true;
                }
            }
            if(_readOnlyGridColumns!=null){
                foreach (var column in _readOnlyGridColumns){
                    column.OptionsColumn.ReadOnly = true;
                }
            }
        }


        #region 数据操作
        
        /// <summary>
        /// 刷新数据
        /// </summary>
        public virtual void RefreshData(){
            OnRefreshData();
            RefreshState();
        }

        /// <summary>
        /// 加载数据
        /// </summary>
        protected virtual void OnLoadData(){
            RefreshState();
        }

        /// <summary>
        /// 加载数据之前处理
        /// </summary>
        protected virtual void BeginLoadData(){
            _lastPosition = DefaultBindingSource.Position;
            DefaultBindingSource.EndEdit();
        }

        /// <summary>
        /// 加载数据之后处理
        /// </summary>
        protected virtual void EndLoadData(){
            if (_lastPosition >= 0 && _lastPosition < DefaultBindingSource.Count){
                DefaultBindingSource.Position = _lastPosition;
            } else if (_lastPosition > DefaultBindingSource.Count - 1){
                DefaultBindingSource.MoveLast();
            } else{
                DefaultBindingSource.MoveFirst();
            }
        }

        /// <summary>
        /// 判断数据操作规则是否许可
        /// </summary>
        /// <param name="rule"></param>
        /// <returns></returns>
        public bool Assert(DataManipulateRule rule){
            return (ManipulateRule & rule) != 0;
        }

        /// <summary>
        /// 获得当前数据行
        /// </summary>
        /// <returns></returns>
        protected DataRow GetCurrentRow(){
            return GetCurrentRow(DefaultBindingSource);
        }

        /// <summary>
        /// 获得指定数据
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        protected DataRow GetCurrentRow(BindingSource source){
            if ((null != source) &&
                (source.Count > 0)){
                object current = source.Current;
                if (current != null){
                    if (current is DataRowView){
                        return ((DataRowView) current).Row;
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 获得指定数据
        /// </summary>
        /// <param name="bindingManager"></param>
        /// <returns></returns>
        protected DataRow GetCurrentRow(BindingManagerBase bindingManager){
            if ((null != bindingManager) &&
                (bindingManager.Count > 0)){
                object current = bindingManager.Current;
                if (current != null){
                    if (current is DataRowView){
                        return ((DataRowView) current).Row;
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 获得指定数据
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        protected DataRow GetCurrentRow(Control control){
            if (control == null){
                return null;
            }
            if (control is GridControl){
                var grid = (GridControl) control;
                return GetCurrentRow(grid.BindingContext[grid.DataSource, grid.DataMember]);
            }
            if (control is DataGrid){
                var grid = (DataGrid) control;
                return GetCurrentRow(grid.BindingContext[grid.DataSource, grid.DataMember]);
            }
            if (control is ListControl){
                var list = (ListControl) control;
                return GetCurrentRow(list.BindingContext[list.DataSource]);
            }
            return null;
        }

        #region 数据操作事件响应

        /// <summary>
        /// 数据验证
        /// </summary>
        public virtual bool DataValidate(){
            if (!Assert(DataManipulateRule.AllowEdit)) {
                DefaultBindingSource.CancelEdit();
                return false;
            }
            DefaultBindingSource.EndEdit();
            RefreshState();
            return Validate();
        }

        /// <summary>
        /// 更新数据时处理
        /// </summary>
        protected virtual void OnUpdateData(){
            if (!Assert(DataManipulateRule.AllowEdit)) {
                throw new NotSupportedException("当前权限不支持编辑操作");
            }
        }

        /// <summary>
        /// 当数据操作规则改变时引发事件
        /// </summary>
        /// <param name="newRule"></param>
        protected virtual void OnManipulateRuleChange(DataManipulateRule newRule){}

        /// <summary>
        /// 新增数据项目事件响应
        /// 默认执行增加项 <see cref="BindingSource.AddNew"/> 方法并调用 <see cref="OnAddedNewData" />
        /// </summary>
        protected virtual object OnAddNewData(){
            Assert(DataManipulateRule.AllowNew);
            DefaultBindingSource.SuspendBinding();
            var newData = DefaultBindingSource.AddNew();
            DefaultBindingSource.ResumeBinding();
            DefaultBindingSource.Position = DefaultBindingSource.Count - 1;
            return newData;
        }

        /// <summary>
        /// 响应编辑数据项目在当前窗口进行编辑事件
        /// </summary>
        protected virtual void OnEditData(){
            Assert(DataManipulateRule.AllowEdit);
        }

        /// <summary>
        /// 查看数据项目事件响应
        /// </summary>
        protected virtual void OnViewData(){
            Assert(DataManipulateRule.AllowView);
        }

        /// <summary>
        /// 删除当前行事件响应
        /// </summary>
        protected virtual void OnDeleteData(){
            Assert(DataManipulateRule.AllowRemove);
        }

        #endregion 数据操作事件响应

        #endregion 数据操作

        #region 窗体事件响应

        /// <summary>
        /// 引发 System.Windows.Forms.Form.Load 事件。
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e){
            base.OnLoad(e);
            DefaultBindingSource.CurrentItemChanged += (s, args) =>RefreshState();
            DefaultBindingSource.CurrentChanged += (s, args) => RefreshState();
            if (!IsEditorsInited){
                InitEditors();
            }
        }

        /// <summary>
        /// 默认数据源是否更改
        /// </summary>
        /// <returns></returns>
        protected virtual bool IsDataSourceChanged(BindingSource bindSource){
            if ((bindSource != null) &&
                ((bindSource.DataSource != null) && (bindSource.DataSource is DataSet))){
                return ((DataSet) DefaultBindingSource.DataSource).HasChanges();
            }
            return false;
        }

        /// <summary>
        /// 刷新当前数据状态
        /// </summary>
        protected internal virtual void RefreshState() {
            if (!DesignMode) {
                Text = IsDataSourceChanged(DefaultBindingSource) ? FormTitle + @"*" : FormTitle;
            }
        }

        protected override void OnClosing(CancelEventArgs e){
            base.OnClosing(e);
            UpdateData(e);
        }

        /// <summary>
        /// 可取消操作的 更新检查
        /// </summary>
        /// <param name="e"></param>
        private void UpdateData(CancelEventArgs e) {
            if (!Assert(DataManipulateRule.AllEdit)) {
                return;
            }
            Visible = true;
            e.Cancel = !DataValidate();
            if (e.Cancel) {
                //return;
            }
            if (IsDataSourceChanged(DefaultBindingSource)) {
                DialogResult result = XtraMessageBox.Show("内容发生变更,是否保存?", "提示信息 [" + FormTitle + "] ",
                                                          MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                switch (result) {
                    case DialogResult.Yes:
                        UpdateData();
                        e.Cancel = false;
                        break;
                    case DialogResult.No:
                        DefaultBindingSource.CancelEdit();
                        e.Cancel = false;
                        break;
                    case DialogResult.Cancel:
                        e.Cancel = true;
                        break;
                }
            }
        }

        #endregion 窗体事件响应
    }
}